package com.evl.trainSeat.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.evl.api.ticket.service.ITicketService;
import com.evl.api.trainOrder.vo.PassengerRQ;
import com.evl.api.trainOrder.vo.TrainOrderCreateRQ;
import com.evl.common.constant.Const;
import com.evl.common.persistence.dao.ScheduleStationMapper;
import com.evl.common.persistence.dao.StationSeatRMapper;
import com.evl.common.persistence.dao.TrainSeatScheduleMapper;
import com.evl.common.persistence.dao.VehicleScheduleMapper;
import com.evl.common.persistence.model.ScheduleStation;
import com.evl.common.persistence.model.StationSeatR;
import com.evl.common.persistence.model.VehicleSchedule;
import com.evl.constant.ErrorContant;
import com.evl.core.vo.BaseResultVo;
import com.evl.core.vo.JsonReturnHelper;
import com.evl.redis.RedisConfig;
import com.evl.redis.RedisLock;
import com.evl.ticketRemainder.vo.TrainSeatScheduleVo;
import com.evl.trainSeat.service.ITrainSeatService;

/**
 * <p>
 * 座位表 服务实现类
 * </p>
 *
 * @author yangliwei
 * @since 2017-06-26
 */
@Service
public class TrainSeatServiceImpl implements ITrainSeatService {

	private Logger log = Logger.getLogger(this.getClass());
	
	@Resource
	VehicleScheduleMapper vehicleScheduleMapper;
	
	@Resource
	ScheduleStationMapper scheduleStationMapper;
	
	@Resource
	StationSeatRMapper stationSeatRMapper;
	
	@Resource
	TrainSeatScheduleMapper trainSeatScheduleMapper;
	
	@Resource
	ITicketService ticketService;
	
	@Resource  
    RedisTemplate<String, ?> redisTemplate;

	public BaseResultVo queryStationSeat(TrainOrderCreateRQ trainOrderVo){

		RedisLock lock = new RedisLock(redisTemplate, Const.DISTRIBUTED_TRANSACTION_BY_CREATE_ORDER, 3000, 5000);
		 try {
			 if(lock.lock()) {
				 //需要加锁的代码
				 
				 //执行业务方法
				return queryTicketsLock(trainOrderVo);
			 }
		 } catch (InterruptedException e) {
			 e.printStackTrace();
		 }finally {
			 //为了让分布式锁的算法更稳键些，持有锁的客户端在解锁之前应该再检查一次自己的锁是否已经超时，再去做DEL操作，因为可能客户端因为某个耗时的操作而挂起，
			 //操作完的时候锁因为超时已经被别人获得，这时就不必解锁了。 ————这里没有做
			 lock.unlock();
		 }
		 
		 return JsonReturnHelper.getSuccessWithNull();
    }
	
	public  BaseResultVo queryTicketsLock(TrainOrderCreateRQ trainOrderVo) {
		
		String staId = trainOrderVo.getStaId()+"";
		String departure = trainOrderVo.getDeparture();
		String arrive = trainOrderVo.getArrive();
		String isRandomSeat = trainOrderVo.getIsRandomSeat();//是否随机选座 0.随机选座 1.在线选座
		
		//判断乘客数量是否为空
		if(trainOrderVo.getUserList() == null || trainOrderVo.getUserList().size()==0){
			return JsonReturnHelper.getFailWithError(ErrorContant.TICKET_PASSENGER_ISNULL_MSG, ErrorContant.TICKET_PASSENGER_ISNULL_CODE);
		}
		
		//判断乘客是否已购当前车次票
		String msg="";
		for(PassengerRQ pass : trainOrderVo.getUserList()){
			StationSeatR staionSeatR = stationSeatRMapper.findStationSeatRByIDF(trainOrderVo.getStaId(), pass.getCardNo());
			if(staionSeatR!=null){
				msg +="["+pass.getName()+"]";
			}
		}
		if(StringUtils.isNotEmpty(msg)){
			return JsonReturnHelper.getFailWithError(msg + ErrorContant.TICKET_PASSENGER_MORE_MSG,ErrorContant.TICKET_PASSENGER_MORE_CODE);
		}
		
		//获取调度火车
		VehicleSchedule vehicleSchedule = vehicleScheduleMapper.selectById(staId);
		
		//乘车车次是否存在
		if(vehicleSchedule ==null){
			return JsonReturnHelper.getFailWithError(ErrorContant.TICKET_TRAINNO_ISVAILD_MSG, ErrorContant.TICKET_TRAINNO_ISVAILD_CODE);
		}
		
		//获取出发站至到达站的的站点线路信息
		List<ScheduleStation> sStaionList = getStationLine(staId, departure, arrive);
		
		//获取对应站点的座位列表（可选）存入map集合
		Map<Integer,List<TrainSeatScheduleVo>> map = new HashMap<Integer, List<TrainSeatScheduleVo>>();
		for (ScheduleStation ss : sStaionList){
			map.put(ss.getId(), trainSeatScheduleMapper.selectTrainSeatSchedulesByStationId(ss.getId()));
		}
		
		//获取每个站点的座位列表（可选）的交集
		List<TrainSeatScheduleVo> intersectionList = new ArrayList<TrainSeatScheduleVo>();
		for(Map.Entry<Integer, List<TrainSeatScheduleVo>> entry : map.entrySet()){
			if(intersectionList.size() == 0){//如何集合为空，赋值
				intersectionList = entry.getValue();
			} else{//取各个站点的集合交集
				intersectionList.retainAll(entry.getValue());
			}
		}
		
		//计算每种席别的座位数量
		Map<String,Integer> seatDetailMap = new HashMap<String, Integer>();
		for(int i=0; i<intersectionList.size(); i++){
			seatDetailMap.put(intersectionList.get(i).getSeatType(),(seatDetailMap.get(intersectionList.get(i).getSeatType())==null?0:seatDetailMap.get(intersectionList.get(i).getSeatType()))+1);
		}
		
		//获取用户数量和所选座位席别
		int remainderNum = trainOrderVo.getUserList().size();
		String remainderType = trainOrderVo.getUserList().get(0).getSeatType();
		
		Map<String,Integer> passMap = new HashMap<String, Integer>();
		for(PassengerRQ pass : trainOrderVo.getUserList()){
			passMap.put(pass.getSeatType(), passMap.get(pass.getSeatType()) == null?0:passMap.get(pass.getSeatType())+1);
		}
		
		//判断余票是否足够
		for (Map.Entry<String, Integer> entry : passMap.entrySet()){
			if(seatDetailMap.get(entry.getKey()) == null && entry.getValue() < seatDetailMap.get(entry.getKey())){
				return JsonReturnHelper.getFailWithError(ErrorContant.TICKET_REMAINDER_INSUFFICIENT_MSG, ErrorContant.TICKET_REMAINDER_INSUFFICIENT_CODE);
			}
		}

		List<StationSeatR> stationSeatRList = new ArrayList<StationSeatR>();
		
		//判断随机选座和在线选座
		if(isRandomSeat.equals(Const.RANDOM_OPTIONS)){
			//随机分配座位
			for(int i =0; i< trainOrderVo.getUserList().size(); i++){
				
				for (TrainSeatScheduleVo tssVo : intersectionList){
					if (tssVo.getSeatType().equals(trainOrderVo.getUserList().get(i).getSeatType())){
						//返回乘客的座位信息到userList
						trainOrderVo.getUserList().get(i).setSeatId(tssVo.getId());
						trainOrderVo.getUserList().get(i).setSeatNo(tssVo.getSeatNo());
						
						intersectionList.remove(tssVo);
						break;
					}
				}
				
				//封装乘客与站点座位的关系
				for(Map.Entry<Integer, List<TrainSeatScheduleVo>> entry : map.entrySet()){
					
					StationSeatR stationSeatR = new StationSeatR();
					stationSeatR.setStationId(entry.getKey());
					stationSeatR.setSeatId(trainOrderVo.getUserList().get(i).getSeatId());
					stationSeatR.setSeatStatus(Const.SEAT_LOCKED);
					stationSeatR.setIdentification(trainOrderVo.getUserList().get(i).getCardNo());
					
					stationSeatRList.add(stationSeatR);
				}
			}
				
		}else if(isRandomSeat.equals(Const.ONLINE_OPTIONS)){
			//在线选座
			
			//判断在线选座的座位是否被占用
			int occupyNum = 0;
			for (int i =0;i<trainOrderVo.getUserList().size();i++){
				PassengerRQ pg = trainOrderVo.getUserList().get(i);
				for (TrainSeatScheduleVo trainSeatScheduleVo : intersectionList){
					if(trainSeatScheduleVo.getId().equals(pg.getSeatId())){
						occupyNum ++;
						break;
					}
				}

				//封装乘客与站点座位的关系
				for(Map.Entry<Integer, List<TrainSeatScheduleVo>> entry : map.entrySet()){
					
					StationSeatR stationSeatR = new StationSeatR();
					stationSeatR.setStationId(entry.getKey());
					stationSeatR.setSeatId(pg.getSeatId());
					stationSeatR.setSeatStatus(Const.SEAT_LOCKED);
					stationSeatR.setIdentification(pg.getCardNo());
					
					stationSeatRList.add(stationSeatR);
					
				}
			}
			if(occupyNum < trainOrderVo.getUserList().size()){
				return JsonReturnHelper.getFailWithError(ErrorContant.TICKET_REMAINDER_INSUFFICIENT_MSG, ErrorContant.TICKET_REMAINDER_INSUFFICIENT_CODE);
			}
			
		}
		
		//将已被占用的座位状态变为锁定
		try {
			
			if(stationSeatRList !=null && stationSeatRList.size()>0){
				stationSeatRMapper.batchUpdate(stationSeatRList);
			}
		} catch (Exception e) {
			e.printStackTrace();
			return JsonReturnHelper.getFailWithError(ErrorContant.TICKET_REMAINDER_LOCKED_MSG, ErrorContant.TICKET_REMAINDER_LOCKED_CODE);
		}
		
		return JsonReturnHelper.getSuccessWithData(trainOrderVo);
	}
	
	
	
	/**
	 * 获取出发站至到达站的的站点线路信息
	 * @param staId
	 * @param departure
	 * @param arrive
	 * @return
	 */
	@Override
	public List<ScheduleStation> getStationLine(String staId, String departure, String arrive){
		
		List<ScheduleStation> sStaionList = ticketService.selectScheduleStations(Integer.parseInt(staId));
		
		//根据开始站至到达站获取对应站点的座位信息
		int fromIndex = 0;
		int toIndex = 0;
		for (int i = 0; i<sStaionList.size(); i++){
			if(sStaionList.get(i).getStationName().equals(departure) ){//从集合取开始站的索引
				fromIndex = i;
			}
			if(sStaionList.get(i).getStationName().equals(arrive)){//从集合取到达站的索引
				toIndex = i;
			}
		}
		//获取到乘客购买的车站集合
		List<ScheduleStation> subList = sStaionList.subList(fromIndex, toIndex);
		
		return subList;
	}
 
	@Override
	public void releaseStationSeatR(List<StationSeatR> list) throws Exception {
		
		try {
			if(list !=null && list.size()>0){
				stationSeatRMapper.batchUpdate(list);
			}
		} catch (Exception e) {
			throw new Exception("更新座位信息失败",e);
		} 
	}
}
